﻿using DynamicToolkit;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq.Expressions;
using DynamicToolkit.Tests.Mocks;
using DynamicToolkit.Tests.Helpers;

namespace DynamicToolkit.Tests
{    
    /// <summary>
    ///This is a test class for XpathExpressionParserTest and is intended
    ///to contain all XpathExpressionParserTest Unit Tests
    ///</summary>
    [TestClass()]
    public class XpathExpressionParserTest
    {

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestClass]
        public class NumericComprisons
        {
            [TestMethod()]
            public void Expression_EqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price == 10.00M;
                string expected = "Price = 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_NotEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price != 10.00M;
                string expected = "Price != 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_GreaterThanExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price > 10.00M;
                string expected = "Price > 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_GreaterThanOrEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price >= 10.00M;
                string expected = "Price >= 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_LessThanExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price < 10.00M;
                string expected = "Price < 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_LessThanOrEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Price <= 10.00M;
                string expected = "Price <= 10.00";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }
        }


        [TestClass]
        public class NonNumericComprisons
        {
            [TestMethod()]
            public void Expression_EqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol == "GOOG";
                string expected = "Symbol = 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_NotEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol != "GOOG";
                string expected = "Symbol != 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_GreaterThanExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol > "GOOG";
                string expected = "Symbol > 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_GreaterThanOrEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol >= "GOOG";
                string expected = "Symbol >= 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_LessThanExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol < "GOOG";
                string expected = "Symbol < 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_LessThanOrEqualExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol <= "GOOG";
                string expected = "Symbol <= 'GOOG'";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }
        }


        [TestClass]
        public class BooleanComprisons
        {
            [TestMethod()]
            public void Expression_TrueExpressionTypeShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Increase == true;
                string expected = "Increase = true";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_NotTrueExpressionTypeShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Increase != true;
                string expected = "Increase != true";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_FalseExpressionTypeShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Increase == false;
                string expected = "Increase = false";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_NotFalseExpressionTypeShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Increase != false;
                string expected = "Increase != false";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }
        }


        [TestClass]
        public class ComplexPredicates
        {
            [TestMethod()]
            public void Expression_BinaryAndAlsoExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol == "GOOG" && s.Price >= 500;
                string expected = "Symbol = 'GOOG' and Price >= 500";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_BinaryOrElseExpressionShouldGenerateCorrespondingXpathExpression()
            {
                Expression<Func<IMockStock, bool>> exp = (s) => s.Symbol == "GOOG" || s.Price >= 500;
                string expected = "Symbol = 'GOOG' or Price >= 500";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }

            [TestMethod()]
            public void Expression_PropertyExpressionShouldGenerateCorrespondingXpathExistenceExpression()
            {
                Expression<Func<IMockStock, string>> exp = (s) => s.Symbol;
                string expected = "Symbol";
                string actual = XpathExpressionParser.Expression(exp);
                Assert.AreEqual(expected, actual);
                XpathAssert.IsValidUnwrappedPredicate(actual);
            }
        }
    }
}
